package cn.glow.readingcloud.book.service.impl;

import  cn.glow.readingcloud.common.pojo.Book;
import cn.glow.readingcloud.book.dao.BookChapterMapper;
import cn.glow.readingcloud.book.service.BookChapterService;
import cn.glow.readingcloud.book.service.BookService;
import cn.glow.readingcloud.common.result.Result;
import cn.glow.readingcloud.common.result.ResultUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import pojo.*;

import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.concurrent.TimeUnit;
import  cn.glow.readingcloud.common.pojo.Book;
/**
 * @Author Glow
 * @Date 2023-04-15 11:37:43
 * @Description
 * @Version 1.0
 */
@Service
public class BookChapterServiceImpl extends ServiceImpl<BookChapterMapper, BookChapter> implements BookChapterService {
    private static final Logger LOGGER = LoggerFactory.getLogger(BookChapterServiceImpl.class);

    @Autowired
    private BookChapterMapper bookChapterMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private BookService bookService;
    @Override
    public Result getBookChapterListByBookId(String bookId) {
        Book book = (Book) bookService.getBookById(bookId).getData();
        if (null == book) {
            return ResultUtil.notFound().buildMessage("该书不存在于本系统哦！");
        }
        //获取缓存的书本章节信息
      List<BookChapterList> list = (List<BookChapterList>) redisTemplate.opsForValue().get("BookChapterList:"+bookId);
            if(list == null || list.size() == 0)
            {
                LambdaQueryWrapper<BookChapter> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(BookChapter::getBookId,bookId);
                Page<BookChapter> page = new Page<>(1,10);
                //如果缓存没有则从数据库取
        bookChapterMapper.selectPage(page,queryWrapper);
                List<BookChapter> chapters = page.getRecords();
                if(chapters.size() > 0)
                {
                    //将指定书本的章节重新封装到list中存到redis内。
                    ListIterator<BookChapter> listIterator =  chapters.listIterator();
                    while(listIterator.hasNext())
                    {
                        BookChapterList bookChapterList = new BookChapterList();
                        BeanUtils.copyProperties(listIterator.next(),bookChapterList);
                        list.add(bookChapterList);
                    }
                    redisTemplate.opsForValue().set("BookChapterList:"+bookId,list,60, TimeUnit.MINUTES);

                }



            }
        return ResultUtil.success(list);
    }

    @Override
    public Result<BookChapter> getChapterById(String bookId, Integer chapterId) {
            BookChapter bookChapter =(BookChapter) redisTemplate.opsForHash().get("BookID:"+bookId+"WithChapter",chapterId);
            if(bookChapter == null)
            {
                LambdaQueryWrapper<BookChapter> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(BookChapter::getBookId,bookId);
                queryWrapper.eq(BookChapter::getId,chapterId);
              bookChapter = bookChapterMapper.selectOne(queryWrapper);
                redisTemplate.opsForHash().put("BookID:"+bookId+"WithChapter",chapterId,bookChapter);
            }
        return ResultUtil.success(bookChapter);
    }

    @Override
    public Result<BookChapterPage> readChapter(String bookId, Integer chapterId) {
        Book book = (Book) bookService.getBookById(bookId).getData();
        if (null == book) {
            return ResultUtil.notFound().buildMessage("该书不存在于本系统哦！");
        }
        BookChapterPage bookChapterPage = new BookChapterPage();

        String contentid =  chapterId.toString();
        if(chapterId == 0)
        {
            contentid = "first";
        }else  if(chapterId == -1)
        {
            contentid = "last";
        }
        BookPreviousAndNextChapterNode chapterNode = this.getChapterNodeData(book.getId(), contentid);
        if (chapterNode == null) {
            // 获取不到节点数据查询首章节
            contentid = "first";
            chapterNode = this.getChapterNodeData(book.getId(), contentid);
            if (chapterNode == null) {
                return ResultUtil.notFound().buildMessage("本书还没有任何章节内容哦！");
            }
        }
        // 获取当前章信息、内容
        String content = this.getChapterContent(bookId, chapterNode.getId());
        BookChapterView current = new BookChapterView(chapterNode.getId(),chapterNode.getName(),content);

        // 上一章、下一章
        BookChapterView pre = null;
        BookChapterView next = null;
        if (chapterNode.getPre() != null) {
            pre = new BookChapterView(chapterNode.getPre().getId(), chapterNode.getPre().getName(), "");
        }
        if (chapterNode.getNext() != null) {
            next = new BookChapterView(chapterNode.getNext().getId(), chapterNode.getNext().getName(), "");
        }

        bookChapterPage.setCurrent(current);
        bookChapterPage.setPre(pre);
        bookChapterPage.setNext(next);
        return ResultUtil.success(bookChapterPage);

    }


    /**
     * 获取前后章节节点数据链表
     * @param bookId
     * @param field
     * @return
     */
    private BookPreviousAndNextChapterNode getChapterNodeData(final Integer bookId, final String field){
        // 缓存获取

        BookPreviousAndNextChapterNode chapterNode = (BookPreviousAndNextChapterNode) redisTemplate.opsForHash().get("book"+bookId+"chapternode",field);

        if (chapterNode != null) {
            return chapterNode;
        }

        // 章节列表
        LambdaQueryWrapper<BookChapter> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BookChapter::getBookId,bookId);
        List<BookChapter> chapterList = bookChapterMapper.selectList(queryWrapper);

        if (chapterList.size() == 0) {
            return null;
        }

        HashMap<String,BookPreviousAndNextChapterNode> map = new HashMap<>();
        // 上一章节节点数据
        BookPreviousAndNextChapterNode pre = null;
        try {
            for (int i = 1; i <= chapterList.size(); i++) {
                BookChapter chapter = chapterList.get(i - 1);
                // 锁章，获取下一章内容
                if (chapter.getLockStatus()) {
                    if (i >= chapterList.size()) {
                        break;
                    }
                    chapter = chapterList.get(i);
                }

                // 得到当前章节节点数据
                BookPreviousAndNextChapterNode curr = new BookPreviousAndNextChapterNode(chapter.getId(), chapter.getName());
                if (pre != null) {
                    curr.setPre(new BookPreviousAndNextChapterNode(pre));
                    pre.setNext(new BookPreviousAndNextChapterNode(curr));
                    // 章节id
                    map.put(pre.getId()+"", pre);
                }

                // 第二章设置前章节点数据
                if (i == 2) {
                    map.put("first", pre);
                }

                // 首章节设置当前节点数据
                if (i == 1) {
                    map.put("first", curr);
                }

                // 存储节点数据
                map.put(curr.getId()+"", curr);
                pre = curr;
            }
            // 最后一章节
            map.put("last", pre);

            redisTemplate.opsForHash().putAll("book"+bookId+"chapternode",map);
        } catch (Exception e) {
            LOGGER.error("生成章节节点数据异常：{}", e);
        }
        return map.get(field);
    }
    /**
     * 获取章节内容
     * @param bookId
     * @param chapterId
     * @return
     */
    private String getChapterContent(String bookId, Integer chapterId){
        String content = "";
        BookChapter chapter = this.getChapterById(bookId, chapterId).getData();
        if (chapter != null) {
            content = chapter.getContent();
        }
        return content;
    }
}
